package com.gitee.ed.example.sqlite;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.text.StrPool;
import org.sqlite.JDBC;
import org.sqlite.SQLiteConfig;
import org.sqlite.SQLiteDataSource;
import org.sqlite.javax.SQLiteConnectionPoolDataSource;

import javax.sql.DataSource;
import java.io.File;
import java.util.function.Consumer;

/**
 * @author hongda.li
 */
public final class TempSqlite {

    private static final String CATEGORY_NAME = "temp-sqlite";

    private static final String DATABASE_NAME = "temp.db";

    private static final File CATEGORY_FILE = FileUtil.mkdir(FileUtil.getTmpDirPath()
            + StrPool.SLASH
            + CATEGORY_NAME);

    private static final DataSource DATA_SOURCE;

    static {
        // 1.UTF-8编码格式；2.临时表数据存放到内存；3.读写完全并发执行；4.执行写入数据后，直接结束
        SQLiteConfig config = new SQLiteConfig();
        config.setEncoding(SQLiteConfig.Encoding.UTF_8);
        config.setTempStore(SQLiteConfig.TempStore.MEMORY);
        config.setJournalMode(SQLiteConfig.JournalMode.WAL);
        config.setSynchronous(SQLiteConfig.SynchronousMode.OFF);
        SQLiteDataSource source = new SQLiteConnectionPoolDataSource(config);
        source.setDatabaseName(DATABASE_NAME);
        source.setUrl(JDBC.PREFIX
                + CATEGORY_FILE.getAbsolutePath()
                + StrPool.SLASH
                + DATABASE_NAME);
        DATA_SOURCE = source;
    }

    private TempSqlite() {
    }

    /**
     * 执行一次性操作
     * 操作执行完后会清除文件夹
     *
     * @param consumer 一次性操作
     */
    public static void withClear(Consumer<DataSource> consumer) {
        // 若已调用过 clear() 方法，则此处会再次创建
        FileUtil.mkdir(CATEGORY_FILE);
        try {
            consumer.accept(getDataSource());
        } finally {
            clear();
        }
    }

    /**
     * 获取单例数据源
     *
     * @return 数据源
     */
    public static DataSource getDataSource() {
        return DATA_SOURCE;
    }

    /**
     * 清除临时文件夹
     */
    public static void clear() {
        try {
            FileUtil.del(CATEGORY_FILE);
        } catch (IORuntimeException ignored) {
            // 如果无法删除此临时文件则忽略异常
        }
    }
}
